package com.ck.schedule;

import com.ck.cache.RedisCacheDao;
import com.ck.common.service.OperationLogService;
import com.ck.company.service.CpDeviceInfoService;
import com.ck.company.service.CpProgramPutinService;
import com.ck.company.service.CpProgramService;
import com.ck.constant.*;
import com.ck.dao.ProgramPutinMapper;
import com.ck.model.common.OperationLog;
import com.ck.model.common.Program;
import com.ck.model.common.ProgramPutin;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.*;

/**
 * 定时任务
 *
 * @author linqiang
 * @date 2018-07-18 11:03
 */
@Component
public class QuartzService {
    private Logger logger = LoggerFactory.getLogger(QuartzService.class);

    @Autowired
    private CpProgramService cpProgramService;
    @Autowired
    private CpDeviceInfoService cpDeviceInfoService;
    @Autowired
    private OperationLogService operationLogService;
    @Autowired
    private ProgramPutinMapper programPutinMapper;
    @Autowired
    private RedisCacheDao redisCacheDao;

    /**
     * 检查节目状态
     */
    @Async
    @Scheduled(cron = "0 0/1 * * * ?")
    public void checkProgramStatus() {
        logger.info("Starting check programStatus...");
        //查询有效的，已审批的节目
        try {
            List<Program> programList = cpProgramService.list(ProgramConstant.DATA_STATUS_EFFECTIVE, ProgramConstant.PROGRAM_STATUS_APPROVED);
            if (CollectionUtils.isNotEmpty(programList)) {
                List<String> versionList = new ArrayList<>();
                for (Program program : programList) {
                    if (null != program.getOverdueTime()) {
                        if (program.getOverdueTime() < System.currentTimeMillis()) {
                            versionList.add(program.getProgramVersion());
                        }
                    } else {
                        ProgramPutin programPutin = programPutinMapper.selectByProgramVersion(program.getProgramVersion());
                        if (null != programPutin && null != programPutin.getPutinEndTime()) {
                            if (programPutin.getPutinEndTime() < System.currentTimeMillis()) {
                                versionList.add(program.getProgramVersion());
                            }
                        }
                    }
                }
                if (CollectionUtils.isNotEmpty(versionList)) {
                    //批量更新节目为‘已过期’
                    long updateTime = System.currentTimeMillis();
                    cpProgramService.batchUpdateProgramToExpiredLocal(versionList, updateTime);
                    logger.info("Batch set program to expired success，programVersion are : "
                            + Arrays.toString(versionList.toArray()));
                    //添加操作日志
                    OperationLog log1 = new OperationLog();
                    log1.setOperationModule(ModuleConstant.MODULE_PROGRAM);
                    log1.setOperationContent("Batch set program to expired success，programVersion are : "
                            + Arrays.toString(versionList.toArray()));
                    log1.setOperationStatus(BusinessConstant.OPERATION_LONG_OPERATION_STATUS_SUCCESS);
                    log1.setOperationTime(updateTime);
                    operationLogService.saveOperationLog(log1);
                    //根据节目版本号查询节目终端mac集合
                    List<String> deviceCodeList = cpDeviceInfoService.listDeviceCodeByCompanyCodeAndProgramVersion(
                            null, versionList);
                    if (CollectionUtils.isNotEmpty(deviceCodeList)) {
                        //批量将过期节目信息更新到缓存中的终端
                        cpDeviceInfoService.flushDeviceStateCache(null, DeviceSettingType.PROGRAM_UPDATE,
                                deviceCodeList, updateTime);
                        logger.info("Check programStatus success and flush device state cache success.");
                        //添加操作日志
                        OperationLog operationLog = new OperationLog();
                        operationLog.setOperationModule(ModuleConstant.MODULE_PROGRAM);
                        operationLog.setOperationContent("Check programStatus success and flush device state cache success.");
                        operationLog.setOperationStatus(BusinessConstant.OPERATION_LONG_OPERATION_STATUS_SUCCESS);
                        operationLog.setOperationTime(updateTime);
                        operationLogService.saveOperationLog(operationLog);
                    }
                }
                logger.info("Check programStatus success");
            }
            logger.info("Finished check programStatus");
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("Check programStatus error, the reason : " + e.getMessage());
        }
    }

    /**
     * 如果设备长时间不在线，更新终端为离线状态
     */
    @Async
    @Scheduled(cron = "0 0/1 * * * ?")
    public void setDeviceOffLine() {
        logger.info("Starting setDeviceOffLine...");
        try {
            Long start = System.currentTimeMillis();
            int effect = cpDeviceInfoService.setDeviceOffLine();
            Long end = System.currentTimeMillis();
            logger.info("更新超时未访问设备为离线状态，耗时：" + (end - start) + "ms.总共更改条数为:" + effect);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("setDeviceOffLine error, the reason : " + e.getMessage(), e);
        }
    }

    /**
     * 清除无用token缓存
     */
    @Async
    @Scheduled(cron = "0 0/5 * * * ?")
    public void clearUselessToken() {
        logger.info("Starting clear UselessToken...");
        try {
            Long start = System.currentTimeMillis();
            Set<Object> tokens = redisCacheDao.getAllKeys(CacheConstant.CK_TOKEN_CACHE_NAME);
            Map<Object, Object> userTokenMappingMap = redisCacheDao.getAllCache(CacheConstant.CK_TOKEN_USER_MAPPING);
            if (null != userTokenMappingMap) {
                Set<String> valueList = new HashSet<>();
                for (Map.Entry<Object, Object> entity : userTokenMappingMap.entrySet()) {
                    if (null != entity.getValue()) {
                        valueList.add(entity.getValue().toString());
                    }
                }
                for (Object token : tokens) {
                    if (null == token) {
                        continue;
                    }
                    if (!valueList.contains(token.toString())) {
                        redisCacheDao.deleteByKey(CacheConstant.CK_TOKEN_CACHE_NAME, token.toString());
                    }
                }
            }
            Long end = System.currentTimeMillis();
            logger.info("清除无用token缓存成功，耗时：" + (end - start) + "ms");
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("clear UselessToken error, the reason : " + e.getMessage(), e);
        }
    }
}
